package com.onluy.frameworkcloud.tools;


import java.io.IOException;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
import javax.crypto.Cipher;

import com.onluy.frameworkcloud.tools.utils.Base64Utils;
import org.apache.commons.codec.binary.Base64;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

public class RsaEncoder {
    public static final String KEY_ALGORITHM = "RSA";
    public static final String CIPHER_ALGORITHM = "RSA/ECB/PKCS1Padding";
    public static final String PUBLIC_KEY = "publicKey";
    public static final String PRIVATE_KEY = "privateKey";
    public static final int KEY_SIZE = 2048;

    public RsaEncoder() {
    }


    /** *//**
     * <p>
     * 生成密钥对(公钥和私钥)
     * </p>
     *
     * @return
     * @throws Exception
     */
    public static Map<String, Object> genKeyPair() throws Exception {
        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
        keyPairGen.initialize(1024);
        KeyPair keyPair = keyPairGen.generateKeyPair();
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
        Map<String, Object> keyMap = new HashMap<String, Object>(2);
        keyMap.put(PUBLIC_KEY, publicKey);
        keyMap.put(PRIVATE_KEY, privateKey);
        return keyMap;
    }

    /** *//**
     * <p>
     * 获取私钥
     * </p>
     *
     * @param keyMap 密钥对
     * @return
     * @throws Exception
     */
    public static String getPrivateKey(Map<String, Object> keyMap)
            throws Exception {
        Key key = (Key) keyMap.get(PRIVATE_KEY);
        return Base64Utils.encode(key.getEncoded());
    }

    /** *//**
     * <p>
     * 获取公钥
     * </p>
     *
     * @param keyMap 密钥对
     * @return
     * @throws Exception
     */
    public static String getPublicKey(Map<String, Object> keyMap)
            throws Exception {
        Key key = (Key) keyMap.get(PUBLIC_KEY);
        return Base64Utils.encode(key.getEncoded());
    }


    public static String encryptRSA(String jsonStr, String publicKeyStr) {
        int length = jsonStr.length();
        int size = length / 100 + (length % 100 == 0 ? 0 : 1);
        StringBuilder sb = new StringBuilder();

        for(int i = 0; i < size; ++i) {
            int start = i * 100;
            int end = (i + 1) * 100;
            if (end > length) {
                end = length;
            }

            String tmp = jsonStr.substring(start, end);
            byte[] bytes = new byte[1024];

            try {
                bytes = (new BASE64Decoder()).decodeBuffer(publicKeyStr);
            } catch (IOException var13) {
                var13.printStackTrace();
            }

            PublicKey publicKey = restorePublicKey(bytes);
            byte[] encodedText = RSAEncode(publicKey, tmp.getBytes());
            String tmpStr = Base64.encodeBase64String(encodedText);
            sb.append(tmpStr).append("#");
        }

        return sb.toString();
    }

    public static String decryptRSA(String jsonStr, String privateKeyStr) {
        String[] base64Strs = jsonStr.toString().split("#");
        byte[] bytes = new byte[1024];

        try {
            bytes = (new BASE64Decoder()).decodeBuffer(privateKeyStr);
        } catch (IOException var7) {
            var7.printStackTrace();
        }

        PrivateKey privateKey = restorePrivateKey(bytes);
        StringBuilder sbuilder = new StringBuilder();

        for(int i = 0; i < base64Strs.length; ++i) {
            sbuilder.append(RSADecode(privateKey, Base64.decodeBase64(base64Strs[i])));
        }

        return sbuilder.toString();
    }

    public static Map<String, String> generateKeyBytes() {
        try {
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
            keyPairGenerator.initialize(2048);
            KeyPair keyPair = keyPairGenerator.generateKeyPair();
            RSAPublicKey publicKey = (RSAPublicKey)keyPair.getPublic();
            RSAPrivateKey privateKey = (RSAPrivateKey)keyPair.getPrivate();
            Map<String, String> keyMap = new HashMap();
            keyMap.put("publicKey", (new BASE64Encoder()).encode(publicKey.getEncoded()));
            keyMap.put("privateKey", (new BASE64Encoder()).encode(privateKey.getEncoded()));
            System.out.println("PUBLIC_KEY=" + (new BASE64Encoder()).encode(publicKey.getEncoded()));
            System.out.print("PRIVATE_KEY=" + (new BASE64Encoder()).encode(privateKey.getEncoded()));
            return keyMap;
        } catch (NoSuchAlgorithmException var5) {
            var5.printStackTrace();
            return null;
        }
    }

    public static PublicKey restorePublicKey(byte[] keyBytes) {
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes);

        try {
            KeyFactory factory = KeyFactory.getInstance("RSA");
            PublicKey publicKey = factory.generatePublic(x509EncodedKeySpec);
            return publicKey;
        } catch (Exception var4) {
            var4.printStackTrace();
            return null;
        }
    }

    public static PrivateKey restorePrivateKey(byte[] keyBytes) {
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes);

        try {
            KeyFactory factory = KeyFactory.getInstance("RSA");
            PrivateKey privateKey = factory.generatePrivate(pkcs8EncodedKeySpec);
            return privateKey;
        } catch (Exception var4) {
            var4.printStackTrace();
            return null;
        }
    }

    public static byte[] RSAEncode(PublicKey key, byte[] plainText) {
        try {
            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            cipher.init(1, key);
            return cipher.doFinal(plainText);
        } catch (Exception var3) {
            var3.printStackTrace();
            return null;
        }
    }

    public static String RSADecode(PrivateKey key, byte[] encodedText) {
        try {
            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            cipher.init(2, key);
            return new String(cipher.doFinal(encodedText));
        } catch (Exception var3) {
            var3.printStackTrace();
            return null;
        }
    }

    public static void main(String[] args) {
        generateKeyBytes();
    }
}
